package osDemo;

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

// 信号量实现同步互斥
public class BarberShop {
    private final int SERVE_TIME = 1;   // 理发师理发时间，单位秒

    Semaphore full = new Semaphore(0);  // 初始的椅子上没有人
    Semaphore empty = new Semaphore(1);  // 初始的椅子为空
    Semaphore chairs = null;    // 等候区的椅子初始数量

    public BarberShop(int MAX_CHAIR) {
        this.chairs = new Semaphore(MAX_CHAIR);
    }

    class Barber {
        private final AtomicBoolean sleeping = new AtomicBoolean(false);

        public Barber() {
            this.sleeping.set(true);
        }

        private void sleep() {
            this.sleeping.set(true);
            System.out.println("barber go to sleep ZZZZZ");
        }

        // 理发师消费有人的座位
        // 理发师只有一个
        public void serve() throws InterruptedException {
            if (!chairs.hasQueuedThreads()) this.sleep();
            full.acquire();

            if (this.sleeping.get()) {
                this.sleeping.set(false);
                System.out.println("barber wakes up ~");
            }
            System.out.println("barber is cutting hair ...");
            TimeUnit.SECONDS.sleep(SERVE_TIME);

            System.out.println(("barber finish ---"));
            empty.release();
        }
    }

    class Customer {
        // 客户生产有人的座位
        public synchronized void goToBarberShop() throws InterruptedException {
            TimeUnit.MILLISECONDS.sleep(new Random().nextInt(400)); // 顾客到达的时间随机
            if (chairs.availablePermits() == 0) {  // 没有等候的椅子
                System.out.println("waiting room is full, customer leaves");
                return;
            }

            chairs.acquire(); // 请求等候的椅子
            System.out.println("a customer get in, and sit on the waiting chair");
            empty.acquire();  // 请求剪发的椅子
            chairs.release(); // 可以去剪发，释放等候的椅子

            System.out.println("a customer leaves waiting chair then sits on the working place");

            full.release();   // 剪完发释放椅子
        }
    }

    public static class Test {
        public static void main(String[] args) {
            BarberShop shop = new BarberShop(5);
            Barber barber = shop.new Barber();
            Customer customer = shop.new Customer();

            new Thread(() -> {  // 一个理发师
                try {
                    while (true)
                        barber.serve();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            for (int i = 0; i < 7; i++) { // 十个客人想来理发
                new Thread(() -> {
                    try {
                        customer.goToBarberShop();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        }
    }
}
